#include <cstdlib>
#include <time.h>

#include "regular.h"
#include <QImage>
#include <QDebug>

RegularObject::RegularObject() {
    this->randomize();
}

RegularObject::RegularObject(const QString &filename, unsigned int width, unsigned int height, unsigned int rows, unsigned int columns) {
    QImage image(filename);

    unsigned int inc_w = width/columns;
    unsigned int inc_h = height/rows;
    unsigned int prp_w = (image.width()-1)/columns;
    unsigned int prp_h = (image.height()-1)/rows;

    for ( unsigned int i = 0; i < rows; i++ ) {
        for ( unsigned int j = 0; j < columns; j++ ) {
            this->add(std::vector<Vertex>({
                                             Vertex(inc_w*j,     qGray(image.pixel(prp_w*j, prp_h*i)),          inc_h*i),
                                             Vertex(inc_w*j,     qGray(image.pixel(prp_w*j, prp_h*(i+1))),      inc_h*(i+1)),
                                             Vertex(inc_w*(j+1), qGray(image.pixel(prp_w*(j+1), prp_h*i)),       inc_h*i)
                                         }));

            this->add(std::vector<Vertex>({
                                             Vertex(inc_w*(j+1), qGray(image.pixel(prp_w*(j+1), prp_h*i)),      inc_h*i),
                                             Vertex(inc_w*j,     qGray(image.pixel(prp_w*j, prp_h*(i+1))),      inc_h*(i+1)),
                                             Vertex(inc_w*(j+1), qGray(image.pixel(prp_w*(j+1), prp_h*(i+1))),  inc_h*(i+1))
                                         }));
        }
    }
}

void RegularObject::randomize(coord width, coord height, std::size_t rows, std::size_t columns) {
    unsigned int increment_w = width/columns;
    unsigned int increment_h = height/rows;

    for ( unsigned int i = 0; i < rows; i++ ) {
        for ( unsigned int j = 0; j < columns; j++ ) {
            this->add(std::vector<Vertex>({
                                              Vertex(increment_w*j, 0, increment_h*i),
                                              Vertex(increment_w*j, 0, increment_h*(i+1)),
                                              Vertex(increment_w*(j+1), 0, increment_h*i)
                                          }));

            this->add(std::vector<Vertex>({
                                              Vertex(increment_w*(j+1), 0, increment_h*i),
                                              Vertex(increment_w*j, 0, increment_h*(i+1)),
                                              Vertex(increment_w*(j+1), 0, increment_h*(i+1))
                                          }));
        }
    }

    srand(time(NULL));
    for ( Vertex *v: this->vertexs ) {
        v->y = (std::rand()%100);
        this->updateLimits(*v);
    }
}

Object *RegularObject::smooth() {
    Object *ret = new Object(*this);

    const std::vector<Vertex *> &new_vertexs = ret->getVertex();
    unsigned int vertex_count = new_vertexs.size();

    for ( unsigned i = 0; i < vertex_count; i++ ) {
        const std::list<const Vertex *> &neighbors = this->vertexs.at(i)->getNeighbors();
        coord sum = 0;
        for ( const Vertex* neighbor: neighbors )
            sum += neighbor->y;
        new_vertexs[i]->y = sum/neighbors.size();
    }

    return ret;
}



void Adair::randomize() {
    this->add(std::vector<Vertex>({
                                      Vertex(-250,  250, -125),
                                      Vertex( 250,  250, -125),
                                      Vertex( 0  ,  250,  125)
                                  }));

    this->add(std::vector<Vertex>({
                                      Vertex(-250, -250, -125),
                                      Vertex( 250, -250, -125),
                                      Vertex( 0  , -250,  125)
                                  }));

    this->add(std::vector<Vertex>({
                                      Vertex(-250,  250, -125),
                                      Vertex(   0,  250,  125),
                                      Vertex(   0, -250,  125),
                                      Vertex(-250, -250, -125)
                                  }));

    this->add(std::vector<Vertex>({
                                      Vertex(   0,  250,  125),
                                      Vertex( 250,  250, -125),
                                      Vertex( 250, -250, -125),
                                      Vertex(   0, -250,  125),
                                  }));

    this->add(std::vector<Vertex>({
                                      Vertex(-250,  250, -125),
                                      Vertex( 250,  250, -125),
                                      Vertex( 250, -250, -125),
                                      Vertex(-250, -250, -125)
                                  }));
}

Adair::Adair() {
    this->randomize();
}

